home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 July: Mac OS SDK / Dev.CD Jul 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw GX / Programming Stuff / Sample Code / Typography Samples / Dave’s Fab Samples ƒ / MenuHandler.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-20  |  11.3 KB  |  375 lines  |  [TEXT/KAHL]

  1. /******************************************************************************\
  2. *
  3. * Apple Macintosh Developer Technical Support
  4. *
  5. * Menu-handling routines
  6. *
  7. * Program: DavesFabSamples
  8. * File:    MenuHandler.c
  9. *
  10. * by:      Forrest Tanaka
  11. *
  12. * Copyright © 1988-1990 Apple Computer, Inc.
  13. * All rights reserved.
  14. *
  15. * 1.0D2 (09/09/93, MD) -- commented out calls to Feature Sets, which are no
  16. *                          longer supported in QuickDraw GX.
  17. *
  18. \******************************************************************************/
  19.  
  20.  
  21. /******************************************************************************\
  22. * Header Files
  23. \******************************************************************************/
  24.  
  25. #include <Desk.h>
  26. #include <Errors.h>
  27. #include <Memory.h>
  28. #include <Menus.h>
  29. #include <Resources.h>
  30.  
  31. #include "DavesFabSamples.h"
  32. #include "MenuHandler.h"
  33. #include "SampleInterface.h"
  34.  
  35.  
  36. /******************************************************************************\
  37. * Constants
  38. \******************************************************************************/
  39.  
  40. #define rMenuBar 128 /* Resource ID of this application’s MBAR resource */
  41.  
  42. #define kNumMenuGuides (mLastMenu - mApple + 1) /* Number of menu guide recs */
  43.  
  44. /******************************************************************************\
  45. * Types
  46. \******************************************************************************/
  47.  
  48. typedef struct
  49. {
  50.     MenuHandle theMenu; /* Handle to this guide’s menu */
  51.     long       enables; /* Current enable flags */
  52. } MenuGuide;
  53.  
  54.  
  55. /******************************************************************************\
  56. * Prototypes
  57. \******************************************************************************/
  58.  
  59. void DoAppleMenu(
  60.     short menuItem);
  61.  
  62. void DoFileMenu(
  63.     short menuItem);
  64.  
  65. void DoSampleMenu(
  66.     short menuItem);
  67.  
  68. void DoMatchingMenu(
  69.     short menuItem);
  70.  
  71. void ResetMenuItems(void);
  72.  
  73.  
  74. /******************************************************************************\
  75. * Variables
  76. \******************************************************************************/
  77.  
  78. MenuGuide gMenuGuides[kNumMenuGuides]; /* Application’s menu guide records */
  79.  
  80. void  (*samples[])(WindowPtr sampleWindow) = {
  81.         AngledCaretsAndHilites,
  82.         AutomaticKerning,
  83.         BaselineAlignment,
  84.         CaseSubstitution,
  85.         ContinuousFlushness,
  86.         ContinuousJustification,
  87.         CrossStreamKerning,
  88.         DirectionOverrides,
  89.         ExtenderBars,
  90.         GetGlyphOffsetsExample,
  91.         GetOffsetGlyphsExample,
  92.         GlyphStretching,
  93.         GlyphSubstitutions,
  94.         GrowingOrShrinkingLines,
  95.         HangingPunctuation,
  96.         ImposedWidth,
  97.         IndicRearrangement,
  98.         JustifyGlyph,
  99.         KerningAdjustments,
  100.         LeftAndRightFactors,
  101.         LetterSpacing,
  102.         LigatureDecomposition,
  103.         LigatureSplits,
  104.         Ligatures,
  105.         NumberStyles,
  106.         OpticalAlignment,
  107.         SmartSwashes,
  108.         SplitPolarizedCarets,
  109.         TrackKerning,
  110.         UnicodeReordering,
  111.         UnlimitedGapAbsorption,
  112.         VerticalLines,
  113.         VerticalSubstitution
  114. };
  115.     
  116.  
  117. /******************************************************************************\
  118. * Public: StartMenus
  119. *
  120. * The menu guide array is initialized with the menu handles and enable flags of
  121. * all menus.
  122. *
  123. * If GetNewMBar couldn’t load the MBAR resource, then it returns nil and the
  124. * error code is in ResError, and I can deal with the error elegantly.  But, if
  125. * the GetNewMBar couldn’t load the menus themselves, then it’ll probably crash.
  126. \******************************************************************************/
  127.  
  128. OSErr StartMenus()
  129. {
  130.     Handle menuBar;   /* Handle to the menu bar from the MBAR resource */
  131.     short  menuIndex; /* Index into menu guide records */
  132.     OSErr  error;
  133.  
  134.     /* Load in the menu bar */
  135.     menuBar = GetNewMBar( rMenuBar );
  136.     if (menuBar != nil)
  137.     {
  138.         /* Set it, then dispose of it because SetMenuBar makes a copy */
  139.         SetMenuBar( menuBar );
  140.         DisposHandle( menuBar );
  141.  
  142.         /* Add the desk accessories to the Apple menu */
  143.         AddResMenu( GetMHandle( mApple ), 'DRVR' );
  144.  
  145.         /* gxInitialize the menu guide array */
  146.         for (menuIndex = 0; menuIndex < kNumMenuGuides; menuIndex++)
  147.         {
  148.             gMenuGuides[menuIndex].theMenu = GetMHandle( menuIndex + mApple );
  149.             gMenuGuides[menuIndex].enables = (**gMenuGuides[menuIndex].
  150.                     theMenu).enableFlags;
  151.         }
  152.  
  153.         /* Draw the menu bar */
  154.         DrawMenuBar();
  155.         error = noErr;
  156.     }
  157.     else
  158.     {
  159.         error = ResError();
  160.         if (error == noErr)
  161.             error = resNotFound;
  162.         if (error != resNotFound && error != memFullErr)
  163.             error = dsSysErr;
  164.     }
  165.     return error;
  166. }
  167.  
  168.  
  169. /******************************************************************************\
  170. * Public: DoMenuChoice
  171. *
  172. * This routine should be self-explanatory.
  173. \******************************************************************************/
  174.  
  175. void DoMenuChoice(
  176.     long menuChoice) /* Return value from MenuSelect or MenuKey */
  177. {
  178.     short menuNum;  /* Menu number of chosen menu */
  179.     short menuItem; /* Item number of chosen menu item */
  180.  
  181.     if (menuChoice != 0)
  182.     {
  183.         /* Get the chosen menu item and menu number */
  184.         menuNum = hiWord( menuChoice );
  185.         menuItem = loWord( menuChoice );
  186.  
  187.         /* Dispatch the appropriate menu-handling routine */
  188.         if (menuNum == mApple)
  189.             DoAppleMenu( menuItem );
  190.         else if (menuNum == mFile)
  191.             DoFileMenu( menuItem );
  192.         else if (menuNum == mSample)
  193.             DoSampleMenu( menuItem );
  194.         HiliteMenu( 0 );
  195.     }
  196. }
  197.  
  198.  
  199. /******************************************************************************\
  200. * Private: DoAppleMenu - Handle an Apple menu item choice
  201. *
  202. * This routine is called whenever it’s determined that the chosen menu item was
  203. * in the Apple menu.  If the chosen menu item that’s passed in the menuItem
  204. * parameter wasn’t the About item, the name of the menu item is retrieved and
  205. * then OpenDeskAcc is called with this name so that the desk accessory by that
  206. * name is opened.  The Process Manager can launch desk accessories, but
  207. * OpenDeskAcc should still be used if the user chooses any item in the Apple
  208. * menu.
  209. \******************************************************************************/
  210.  
  211. static void DoAppleMenu(
  212.     short menuItem) /* Chosen menu item */
  213. {
  214.     Str255 daName; /* Name of the chosen DA */
  215.     short  refNum; /* Reference number of the DA, ignored */
  216.  
  217.     if (menuItem != iAbout)
  218.     {
  219.         GetItem( GetMHandle( mApple ), menuItem, /*<*/daName );
  220.         refNum = OpenDeskAcc( daName );
  221.     }
  222. }
  223.  
  224.  
  225. /******************************************************************************\
  226. * Private: DoFileMenu - Handle a File menu item choice
  227. *
  228. * This routine is called whenever it’s determined that the chosen menu item was
  229. * in the File menu.  The item number of the chosen menu item is passed in the
  230. * menuItem parameter.
  231. \******************************************************************************/
  232.  
  233. static void DoFileMenu(
  234.     short menuItem) /* Chosen menu item */
  235. {
  236.     if (menuItem == iClose)
  237.         CloseWindow( FrontWindow() );
  238.     else if (menuItem == iQuit)
  239.         DoQuit();
  240. }
  241.  
  242.  
  243. /******************************************************************************\
  244. * Private: DoSampleMenu - Handle a Sample menu item choice
  245. *
  246. * This routine is called whenever it’s determined that the chosen menu item was
  247. * in the Sample menu.  The item number of the chosen menu item is passed in the
  248. * menuItem parameter.
  249. \******************************************************************************/
  250.  
  251. static void DoSampleMenu(
  252.     short menuItem) /* Chosen menu item */
  253. {
  254.     WindowPtr sampleWindow; /* Pointer to the new sample window */
  255.     Rect      windowRect;   /* Global gxRectangle of window */
  256.     Str255    itemString;
  257.  
  258.     if (FrontWindow() != noErr)
  259.         CloseWindow( FrontWindow() );
  260.  
  261.     SetRect( &windowRect, 10, 50, 630, 470 );
  262.  
  263.     sampleWindow = NewWindow( nil, &windowRect, "\p", true,
  264.             documentProc, (WindowPtr)-1L, true, 0L );
  265.  
  266.     GetItem( GetMHandle(mSample), menuItem, itemString);
  267.     SetWTitle( sampleWindow, itemString );
  268.     (samples[menuItem-1])( sampleWindow );
  269.     
  270. }
  271.  
  272.  
  273. /******************************************************************************\
  274. * Public: FixMenus
  275. *
  276. * FixMenus first disables every available menu item.  Then the most basic menu
  277. * items are enabled.  The windowKind field of the front window is then checked.
  278. * If there is a window open, FixMenus calls a routine that’s responsible for
  279. * that kind of window to enable any menu items that are relevant to that kind of
  280. * window.
  281. *
  282. * If the front window is a modal dialog, then the basic set of menu items are
  283. * ! enabled, and the entire Apple menu is disabled.
  284. *
  285. * After this is done, the menu bar might have to be redrawn to reflect the new
  286. * conditions.  So, FixMenus go through every menu to determine if the state of
  287. * the entire menu has changed.  The MenuGuide records are used to help determine
  288. * this.  If the state of any many has changed, then the menu bar is redrawn.
  289. \******************************************************************************/
  290.  
  291. void FixMenus()
  292. {
  293.     WindowPtr  currWindow; /* Pointer to the front-most window */
  294.     MenuHandle aMenu;      /* Handle to menu being enabled */
  295.     long       oldEnables; /* True if 1+ items enabled when FixMenus called */
  296.     long       newEnables; /* True if 1+ items enabled after menus fixed */
  297.     Boolean    mustRedraw; /* True if menu bar has to be redrawn */
  298.     short      numItems;   /* Number of items in a menu */
  299.     short      menuIndex;  /* Index into menu guide array */
  300.  
  301.     /* Start by disabling all menus */
  302.     ResetMenuItems();
  303.  
  304.     /* Front-most window determines most menu enabling/disabling */
  305.     currWindow = FrontWindow();
  306.     if (currWindow != nil)
  307.     {
  308.         aMenu = GetMHandle( mFile );
  309.         EnableItem( aMenu, iClose );
  310.     }
  311.     else
  312.     {
  313.         aMenu = GetMHandle( mFile );
  314.         DisableItem( aMenu, iClose );
  315.     }
  316.  
  317.     /* Assume we don’t have to redraw the menu bar */
  318.     mustRedraw = false;
  319.  
  320.     /* Check through every menu to see if there are any enabled items in it */
  321.     for (menuIndex = 0; menuIndex < kNumMenuGuides; menuIndex++)
  322.     {
  323.         /* Grab the old and new enable flags excluding flag for entire menu */
  324.         oldEnables = gMenuGuides[menuIndex].enables & 0xFFFFFFFE;
  325.         newEnables = (**gMenuGuides[menuIndex].theMenu).enableFlags &
  326.                 0xFFFFFFFE;
  327.  
  328.         /* Shift left so that we only see flags for existing items */
  329.         numItems = CountMItems(gMenuGuides [menuIndex].theMenu);
  330.         oldEnables = oldEnables << (31 - numItems);
  331.         newEnables = newEnables << (31 - numItems);
  332.  
  333.         /* Determine if the menu bar must be redrawn */
  334.         if (((oldEnables != 0) && (newEnables == 0)) || numItems == 0)
  335.         {
  336.             /* Had some items enabled, now has no items enabled, redraw */
  337.             DisableItem( gMenuGuides[menuIndex].theMenu, 0 );
  338.             mustRedraw = true;
  339.         }
  340.         else if ((oldEnables == 0) && (newEnables != 0))
  341.         {
  342.             /* Had no items enabled, now has some items enabled, redraw */
  343.             EnableItem( gMenuGuides[menuIndex].theMenu, 0) ;
  344.             mustRedraw = true;
  345.         }
  346.  
  347.         /* Update our copy of the enable flags */
  348.         gMenuGuides[menuIndex].enables = (**gMenuGuides[menuIndex].theMenu).
  349.                 enableFlags;
  350.     }
  351.  
  352.     /* If at least one menu has changed state, must redraw the menu bar */
  353.     if (mustRedraw)
  354.         DrawMenuBar();
  355. }
  356.  
  357.  
  358. /******************************************************************************\
  359. * Private: ResetMenuItems - Disable any disableable items and clear marks
  360. *
  361. * Disabling all the menu items is done bruteforcedly.  It could easily be done
  362. * by looping through each menu and disabling every item that comes up (disabling
  363. * the gxFont menu is done this way), but I thought doing it using the brute-force
  364. * method was clearer.  Then again. . .
  365. \******************************************************************************/
  366.  
  367. static void ResetMenuItems ()
  368. {
  369.     MenuHandle aMenu; /* Handle to each menu we’re disabling */
  370.  
  371.     /* Disable items in the File menu */
  372.     aMenu = GetMHandle( mFile );
  373.     DisableItem( aMenu, iClose );
  374. }
  375.